﻿using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using DreamStore.WebShop.Extensibility;
using DreamStore.WebShop.Helpers;
using DreamStore.WebShop.Models;
using DreamStore.WebShop.Services;
using DreamStore.WebShop.ViewModels;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Mvc;
using Orchard.Security;
using Orchard.Themes;
using Orchard.ContentManagement;

namespace DreamStore.WebShop.Controllers
{
  
    public class CheckoutController : Controller
    {
        private readonly dynamic _shapeFactory;
        private readonly IAuthenticationService _authenticationService;
        private readonly ICustomerService _customerService;
        private readonly IMembershipService _membershipService;
        private readonly Localizer _t;
        private readonly IShoppingCart _shoppingCart;
        private readonly IEnumerable<IEmailSenderServiceProvider> _emailSenderServiceProviders; 

        public CheckoutController(IShapeFactory shapeFactory, IAuthenticationService authenticationService, ICustomerService customerService, IMembershipService membershipService, IShoppingCart shoppingCart, IEnumerable<IEmailSenderServiceProvider> emailSenderServiceProviders)
        {
            this._shapeFactory = shapeFactory;
            this._authenticationService = authenticationService;
            this._customerService = customerService;
            this._membershipService = membershipService;
            this._t = NullLocalizer.Instance;
            this._shoppingCart = shoppingCart;
            this._emailSenderServiceProviders = emailSenderServiceProviders;
        }

        //Get
        [Themed]
        public ActionResult SignupOrLogin()
        {
            if (_authenticationService.GetAuthenticatedUser() != null)
            {
                return RedirectToAction("SelectAddress");
            }

            var shape = _shapeFactory.SignupOrLogin();
            return new ShapeResult(this, shape);
        }



        //Get
        [Themed]
        public ActionResult Signup()
        {
            var shape = _shapeFactory.Checkout_Signup();
            return new ShapeResult(this, shape);
        }
       
        [Themed,HttpPost]
        public ActionResult Signup(SignupViewModel signup)
        {
            if (!ModelState.IsValid)
            {
                return new ShapeResult(this, _shapeFactory.Checkout_Signup(Signup: signup));
            }

            var customer = _customerService.CreateCustomer(signup.Email, signup.Password);
            customer.FirstName = signup.FirstName;
            customer.LastName = signup.LastName;
            customer.Title = signup.Title;

            _authenticationService.SignIn(customer.User, true);

            foreach (var provider in _emailSenderServiceProviders)
            {
                provider.SendSignupMail(customer.User, customer);
                //Just use the first enabled provider - therefor break!
                break;
            }
            
            return RedirectToAction("SelectAddress");
           
        }

        //Get
        [Themed]
        public ActionResult Login()
        {
            var shape = _shapeFactory.Checkout_Login();
            return new ShapeResult(this, shape);
        }

        [Themed,HttpPost]
        public ActionResult Login(LoginViewModel login)
        {
            if (!ModelState.IsValid)
            {
                var shape = _shapeFactory.Checkout_Login(Login: login);
                return new ShapeResult(this, shape);
            }

            var user = _membershipService.ValidateUser(login.Email, login.Password);

            if (user == null)
            {
                ModelState.AddModelError("Email", _t("Incorrect username or password").ToString());
            }

            if (!ModelState.IsValid)
            {
                var shape = _shapeFactory.Checkout_Login(Login: login);
                return new ShapeResult(this, shape);
            }

            _authenticationService.SignIn(user, login.CreatePersistentCookie);

            return RedirectToAction("SelectAddress");
        }

        //Get
        [Themed]
        public ActionResult SelectAddress()
        {
            var currentUser = _authenticationService.GetAuthenticatedUser();
            if (currentUser == null)
            {
                throw new OrchardSecurityException(_t("Login required"));
            }

            var customer = currentUser.ContentItem.As<CustomerPart>();
            var invoiceAdress = _customerService.GetAddress(customer.Id, "InvoiceAddress");
            var shippingAddress = _customerService.GetAddress(customer.Id, "ShippingAddress");

            var addressViewModel = new AddressesViewModel
                                   {
                                       InvoiceAddress = MapAddress(invoiceAdress),
                                       ShippingAddress = MapAddress(shippingAddress)
                                   };
            var shape = _shapeFactory.Checkout_SelectAddress(Addresses: addressViewModel);

            if (string.IsNullOrWhiteSpace(addressViewModel.InvoiceAddress.Name))
            {
                addressViewModel.InvoiceAddress.Name = string.Format("{0} {1} {2}", customer.Title, customer.FirstName, customer.LastName);
            }
            return new ShapeResult(this, shape);
        }

        [Themed,HttpPost]
        public ActionResult SelectAddress(AddressesViewModel addresses)
        {
            var currentUser = _authenticationService.GetAuthenticatedUser();
            if (currentUser == null)
            {
                throw new OrchardSecurityException(_t("Login required"));
            }

            if (!ModelState.IsValid)
            {
                var shape = _shapeFactory.Checkout_SelectAddress(Addresses: addresses);
                return new ShapeResult(this, shape);
            }

            var customer = currentUser.ContentItem.As<CustomerPart>();
            MapAddress(addresses.InvoiceAddress, "InvoiceAddress", customer);
            MapAddress(addresses.ShippingAddress, "ShippingAddress", customer);

            return RedirectToAction("Summary");
        }

        //Get
        [Themed]
        public ActionResult Summary()
        {
            var user = _authenticationService.GetAuthenticatedUser();
            if (user == null)
            {
                throw new OrchardSecurityException(_t("Login required"));
            }

            dynamic invoiceAddress = _customerService.GetAddress(user.Id, "InvoiceAddress");
            dynamic shippingAddress = _customerService.GetAddress(user.Id, "ShippingAddress");
            dynamic shoppingCartShape = _shapeFactory.ShoppingCart();

            var query = _shoppingCart.GetProducts().Select(tuple => _shapeFactory.ShoppingCartItem(
                Product: tuple.Item1,
                ContentItem: tuple.Item1.ContentItem,
                Quantity: tuple.Item2
                ));

            shoppingCartShape.ShopItems = query.ToArray();
            shoppingCartShape.Total = _shoppingCart.Total();
            shoppingCartShape.Subtotal = _shoppingCart.Subtotal();
            shoppingCartShape.Vat = _shoppingCart.Vat();

            var shape = _shapeFactory.Checkout_summary(
                ShoppingCart: shoppingCartShape,
                InvoiceAddress: invoiceAddress,
                shippingAddress: shippingAddress);

            return new ShapeResult(this, shape);
        }

        private AddressViewModel MapAddress(AddressPart addressPart)
        {
            dynamic address = addressPart;
            var addressViewModel = new AddressViewModel();

            if (addressPart != null)
            {
                addressViewModel.Name = address.Name.Value;
                addressViewModel.AddressLine1 = address.AddressLine1.Value;
                addressViewModel.AddressLine2 = address.AddressLine2.Value;
                addressViewModel.Zipcode = address.Zipcode.Value;
                addressViewModel.City = address.City.Value;
                addressViewModel.Country = address.Country.Value;
            }

            return addressViewModel;
        }

        private AddressPart MapAddress(AddressViewModel source, string addressType, CustomerPart customerPart)
        {
            var addressPart = _customerService.GetAddress(customerPart.Id, addressType) ?? _customerService.CreateAddress(customerPart.Id, addressType);
            dynamic address = addressPart;

            address.Name.Value = source.Name.TrimSafe();
            address.AddressLine1.Value = source.AddressLine1.TrimSafe();
            address.AddressLine2.Value = source.AddressLine2.TrimSafe();
            address.Zipcode.Value = source.Zipcode.TrimSafe();
            address.City.Value = source.City.TrimSafe();
            address.Country.Value = source.Country.TrimSafe();

            return addressPart;
        }
    }
}
